﻿//scfsdf

//#define BYTES2SHORTINT(a, b) (((a) & 0xff) | (((b) & 0xff) << 8))
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace Dt261.ble
{
    public enum CommandError
    {
        Command_NoError = 0X00,
        Command_IndexError,
        Command_DataError,
        Command_CheckError,
        Command_OperateError,
        Command_ElseError,

        Command_Send = 0XFF
    };

    public enum CommandType
    {
        START = 0x00,

        CommandType_DeviceFactory = 0x11,          //设备厂家信息
        CommandType_DeviceSerial = 0x12,           //设备系列号
        CommandType_UserInfo = 0x13,               //客户信息
        CommandType_HardDeviceVersion = 0x14,      //硬件版本号
        CommandType_SoftVersion = 0x15,            //软件版本号




        //CommandType_TestMethod = 0x16,//测试模式

        //+++1.3
        CommandType_KeepDB = 0x19,//01保持00不
        CommandType_ViewSectct = 0x20,    // 界面选择
                                          //00 纯音界面

        CommandType_HeadPhoneTypeSelect = 0x21,    //耳机类型选择
                                                   //00 气导耳机
        CommandType_EarSelect = 0x22,              //左右耳选择
                                                   //00 左耳 01右耳

        //--1.4
        CommandType_HeadPhoneIsInsert = 0x23,      //耳机在位指示
        CommandType_TestToneReverse = 0x24, //反转测试给音
                                            //--1.4


        CommandType_MaskingTone = 0x31,            //掩蔽音使能
                                                   //00 关闭掩蔽音 01 开启对侧掩蔽音
        CommandType_MaskingToneTypeSelect = 0x32,  //掩蔽音类型
                                                   //00 白噪声 01 窄带白噪声

        CommandType_MaskingToneValue = 0x33,       //掩蔽音电平
                                                   //-10~120dB（实际发送数据增大10，即0~130）
                                                   //--1.4

        CommandType_TalkToneAdd = 0x39,             //通话增益，30-45，0x1E --0x2D
        CommandType_TestToneHz = 0x40,             //测试音频率
                                                   //--1.4
        CommandType_TestToneSet = 0x41,            //固定测试音频率
                                                   //1-11、代表125~8000Hz
        CommandType_TestToneValue = 0x42,          //测试音输出电平
                                                   //-10~120dB（实际发送数据增大10，即0~130）
        CommandType_TestTonePlayTime = 0x43,       //测试音输出时间
                                                   //1  0.5秒
                                                   //    2  1秒
                                                   //    4  2秒
                                                   //    0  非定时给音，由开始给音来确定
        CommandType_TestToneType = 0x44,           //测试音类型
                                                   //1  纯音
                                                   //2  啭音

        CommandType_TestStartAndStop = 0x45,//开始测试给音
                                            //0  停止
                                            //1  开始
                                            //1.4
        CommandType_SetHeadphoneValue = 0x62,//  写气导骨导校准值命令
        CommandType_SetCoverValue = 0x64,//  写掩蔽音校准值

        CommandType_SaveValue = 0x6A,//1)    保存准值命令
        CommandType_GetHeadphoneValue = 0xE3,//1)    校准值读取指令
        CommandType_GetCoverValue = 0xE4,////E3 是发送或接受测试音校准值，E4是发送或接受掩蔽音校准值

        //1)    RESPONSE按键响应指令
        CommandType_Response = 0xE2,//
                                    //    00松开
                                    //    01 按下

        //    CommandType_ResponseE3=0xE3,//
        //    CommandType_ResponseE4=0xE4,//
        //end 1.4

        CommandType_TestTalkBack = 0x46,//言语对讲
                                        //    00: 通话使能
                                        //    01：关闭通话


        //--1.4
        CommandType_TestDBStep = 0x47,//测试音输出电平步进

        //+++1.3
        CommandType_TestToneCover = 0x48,//   测试音掩蔽




        CommandType_TestResult = 0x51,             //查询当前气导耳机测试结果
        CommandType_TestRusultByN = 0x52,          //查询第n个位置存储测试结果
        CommandType_TestBoneResult = 0x53,//查询当前骨导耳机测试结果
        CommandType_TestBoneResultByN = 0x54,//查询第n个骨导测试结果

        CommandType_AirHeadphoneValue = 0xF0,//测试输出气导耳机电平校准表
        CommandType_BoneHeadphoneValue = 0xF1,//测试输出骨导耳机电平校准表

        //+++1.3
        CommandType_ClearHeadphoneValue = 0xA0,// 输出电平骨导耳机校准值



        //    1)    RESPONSE按键响应指令
        //    RESPONSE按键响应指令：（设备->上位机）
        //    4E 01 01 C3 FF 41 01 00 42 01 00 11 11 4E
        //    该指令为测试指令，所以识别指令是：0XC3
        CommandType_SetBLERate = 0xF5,//BLE蓝牙波特率设置
        CommandType_SetChuankou4Rate = 0xF6,//串口4波特率设置
        CommandType_SetPGA2311LineMicValue = 0xF7,//1)    PGA2311调节LINE、MIC校准值
        CommandType_SetAIC23LineMicValue = 0xF7,//1)    AIC23调节LINE、MIC校准值设置


        CommandType_ToneTest = 0xF9,//纯音检测，“通”，“断”设置置
        CommandType_Reset = 0xFA,//恢复开机状态设置
        CommandType_SetInitValue = 0xFB,//写入初始校准值

        CommandType_SetBLETime = 0xFD,// BLE广播间隔设置
        CommandType_StartCall = 0xFE,//  通话按钮
                                     //--1.4


        //end
        END = 0xFF



    };

    public enum CommandAction
    {
        // 设置参数值命令	0XC1;查询参数值命令	0XC2 ;测试应答	0xC3
        CommandAction_Set = 0XC1,
        CommandAction_Query = 0XC2,
        CommandAction_Reply = 0XC3,

    };






    //命令体
    class CommandInfo
    {

        CommandType type;
        // byte length;
        Byte length;
        Byte[] body;

        public CommandInfo(CommandType type, Byte[] info)
        {
            this.type = type;
            this.body = new byte[info.Length];
            Array.Copy(info,body,info.Length);
            this.length = (Byte)body.Length;
        }
        public CommandInfo(CommandType type, String info)
        {
            this.type = type;
            this.body = TLJConvert.strToToHexByte(info);
            this.length =(Byte)body.Length;
        }

        public static string parseWithC3HexData(Byte[] data)
        {
            if (data.Length <= 0)
            {
                //NSDictionary* userInfo = [NSDictionary dictionaryWithObject: @"C3命令数据长度错误"                                                                      forKey: NSLocalizedDescriptionKey];
                return "C3命令数据长度错误";//[NSError errorWithDomain:@"www.tinglibao.com" code:Command_DataError userInfo:userInfo];
            }
            else
            {
                Byte[] dataBuffer = data;

                //NSMutableDictionary* retDict = [NSMutableDictionary dictionary];

                int len = dataBuffer[1];
                //NSNumber* value = nil;
                int value;
                //NS
                String key = "";
                if (dataBuffer[0] == 0x40)
                {
                    key = dataBuffer[2].ToString();
                }
                else if (dataBuffer[0] == 0x41)
                {
                    //NSDictionary* d = @{@"1":@"125",@"2":@"250",@"3":@"500",@"4":@"750",@"5":@"1000",@"6":@"1500",@"7":@"2000",@"8":@"3000",@"9":@"4000",@"10":@"6000",@"11":@"8000"};
                    String[] d = { "0",
                        "125",
                        "250",
                        "500",
                        "750",
                        "1000",
                        "1500",
                        "2000",
                        "3000",
                        "4000",
                        "6000",
                        "8000" };
                    Byte index = dataBuffer[2];
                    key = d[index];
                }//

           if (dataBuffer[0] == 0xe2)
                {
                    //测试音地址是0xE3,掩蔽音地址是0xE  <e30109e4 0109>
                    //               00松开
                    //               01 按下

                    int valu = dataBuffer[2];//

                    //Dictionary<string, byte[]> dict = new Dictionary<string, byte[]>();

                    //dict.Add("NEWREPSTAUS_YUANSHI",)
                    //               if(value)
                    //               {
                    //                   [retDict setValue:value forKey:NEWREPSTAUS_ISON];
                    //                   [retDict setValue:data forKey: NEWREPSTAUS_YUANSHI];

                    //                   [[NSNotificationCenter defaultCenter]
                    //postNotificationName:NEWREPSTAUS object:nil userInfo:retDict];

                    DMSkin.Core.Broadcast.PushBroadcast("NEWREPSTAUS", dataBuffer);

                    //               }

                }
                else if (dataBuffer[0] == 0xe3 && dataBuffer[3] == 0xe4)
                {
                    //测试音地址是0xE3,掩蔽音地址是0xE  <e30109e4 0109>
                    //            NSNumber* value = [NSNumber numberWithChar: dataBuffer[2]];//
                    //NSNumber* value2 = [NSNumber numberWithChar: dataBuffer[5]];//

                    //            if(value && value2)
                    //            {
                    //                [retDict setValue:value forKey:NEWCORRECTDATA_CESHIYIN];
                    //                [retDict setValue:value2 forKey:NEWCORRECTDATA_JIAOZHUNYIN];
                    //                [retDict setValue:data forKey: NEWCORRECTDATA_YUANSHI];
                    //                [[NSNotificationCenter defaultCenter]
                    //postNotificationName:NEWCORRECTDATA object:nil userInfo:retDict];
                    //            }


                    Console.WriteLine("发送通知NEWCORRECTDATA：" + TLJConvert.byteToHexStr(dataBuffer));
                    DMSkin.Core.Broadcast.PushBroadcast("NEWCORRECTDATA", dataBuffer);

                }

                else if (dataBuffer[0] == 0xfd)
                {



                    //           [retDict setValue:data forKey: NEWWOSHOU_YUANSHI];
                    //                  [[NSNotificationCenter defaultCenter]
                    //postNotificationName:NEWWOSHOU object:nil userInfo:retDict];

                    //           NSLog(@"发送通知");




                }
                else if (dataBuffer.Length > 5 && dataBuffer[2 + len] == 0x42)
                {

                    //uint8_t len2 = dataBuffer[1+2+len];
                    value = dataBuffer[2 + 2 + len];//db

                    // if(value)
                    {
                        //[retDict setValue:value forKey:key];
                        DMSkin.Core.Broadcast.PushBroadcast("NEWTESTDATA", data);
                        //[[NSNotificationCenter defaultCenter]postNotificationName:NEWTESTDATA object:nil userInfo:retDict];
                    }

                }
                else
                {

                }



                    return null;

            }


        }

        public static String parseWithHexData(Byte[] data, ArrayList infos)
        {
            if (data.Length > 2)
            {
                Byte[] dataBuffer = data;


                int index = 0;

                while (index + 1 < data.Length)
                {

                    if (1 == 1)
                    {
                        CommandType type = (CommandType)dataBuffer[index];
                        int length = dataBuffer[1];
                        // NSData* body = [NSData dataWithBytes: dataBuffer +  length: length];
                        Byte[] unit = dataBuffer.Skip(index + 2).Take(length).ToArray();
                        // [[CommandInfo alloc] initWithCommandType:type info:body];
                        CommandInfo info = new CommandInfo(type, unit);

                        infos.Add(info);

                        index += 2 + length;
                       

                    }
                    else
                    {
                        //NSDictionary* userInfo = [NSDictionary dictionaryWithObject: @"命令不支持错误"                                                                      forKey: NSLocalizedDescriptionKey];
                        //* error =  [NSError errorWithDomain: @"www.tinglibao.com" code: Command_IndexError userInfo: userInfo];

                        //return nil;
                        return "命令不支持错误";
                    }
                }




            }
            return "命令长度错误";
            //-(instancetype) initwithcommandtype:(enum commandtype)type info:(nsdata*) info;
            //-(nserror*) parsewithhexdata:(nsdata*) data;
            //+(nsarray*) parsewithhexdata:(nsdata*) data error:(nserror**) error;
            //+(bool) iscommandaccept:(uint8_t) type;
        }

        public Byte[] getProtocolHex()
        {
            //Byte[] g = BitConverter.GetBytes(length);
            Byte[] b = body;

            Byte[] ret2 = new Byte[1 + 1 + b.Length];
            ret2[0] =(Byte)type;
            ret2[1] = length;
            Array.Copy(b, 0, ret2, 1 + 1, b.Length);


            return ret2;
        }
    }
    //命令单元
    class CommandUnit
    {


        byte version;//协议版本号：1byte，目前暂定为0X01, 接收方对此数据不解析。
        byte keep_back;//备用：1byte，目前暂定为0X01, 接收方对此数据不解析。
        CommandAction command_action;//    设置参数值命令	0XC1;查询参数值命令	0XC2 ;测试应答	0xC3
        byte reply_flag;// 应答标志：作为命令的主动发起方，该字段填0XFF，被动接收方对该字段不解析。如果接收方该字段非0XFF，则表明最近收到的命令无法处理或出错。主发起方收到对方应答标志非0X00的应答后，对“命令体”不解析、不处理。只有应答标志为0X00，“命令体长度”和“命令体”才有意义。
                        //@property(readonly) CommandInfo* command_info;
        ArrayList command_infos;
        //    @property(nonatomic,readonly)NSMutableArray<CommandInfo*>* command_infos;

        //-(instancetype) initWithCommandType:(enum CommandType)type action:(enum CommandAction)action infos:(NSArray<NSData*>*) infos;
        //-(instancetype) initWithReplyCommand:(enum CommandAction)action info:(NSData*) info;
        //-(instancetype) initWithCommandType:(enum CommandType)type action:(enum CommandAction)action info:(NSData*) info;
        //-(void) appendWithCommandType:(enum CommandType)type info:(NSData*) info;
        //-(void) appendWithCommandInfo:(CommandInfo*) info;
        //-(NSError*) parseWithHexData:(NSData*) data;
        //    @end
        public CommandUnit(CommandType type, CommandAction action, ArrayList infos)
        {
            this.version = 0X01;
            this.keep_back = 0X01;
            this.reply_flag = 0XFF;
            this.command_action = action;
            //_command_info = [[CommandInfo alloc] initWithCommandType:type info:info];
            this.command_infos = new ArrayList();

            for (int i = 0; i < infos.Count; i++)
            {
                String s = (String)infos[i];
                //Byte[] infoData = System.Text.Encoding.Default.GetBytes(s);
                CommandInfo info = new CommandInfo(type, s);
                this.command_infos.Add(info);
            }
        }

        public CommandUnit(CommandAction action)
        {
            this.version = 0X01;
            this.keep_back = 0X01;
            this.reply_flag = 0XFF;
            if (action == CommandAction.CommandAction_Reply)
                 this.reply_flag = 0X00;
            this.command_action = action;
            //_command_info = [[CommandInfo alloc] initWithCommandType:type info:info];
            this.command_infos = new ArrayList();
        }

        public CommandUnit()
        {
            this.version = 0X01;
            this.keep_back = 0X01;
            this.reply_flag = 0XFF;
            //_command_info = [[CommandInfo alloc] initWithCommandType:type info:info];
            this.command_infos = new ArrayList();
        }
        public void appendWithCommandType(CommandType type, String infoData)
        {
            CommandInfo info = new CommandInfo(type, infoData);
            this.command_infos.Add(info);
        }


        public void appendWithCommandType(CommandType type, ArrayList infos)
        {
            for (int i = 0; i < infos.Count; i++)
            {
                String s = (String)infos[i];
                //Byte[] infoData = System.Text.Encoding.Default.GetBytes(s);
                CommandInfo info = new CommandInfo(type, s);
                this.command_infos.Add(info);
            }
        }



    public void appendWithCommandType(CommandType type, Byte[] infoData)
        {
            CommandInfo info = new CommandInfo(type, infoData.ToString());
            this.command_infos.Add(info);
        }

        public void appendWithCommandInfo(CommandInfo info)
        {
            this.command_infos.Add(info);
        }

        public string parseWithHexData(Byte[] data)
        {
            if (data.Length > 4)
            {
                Byte[] dataBuffer = data;

                this.version = dataBuffer[0];
                this.keep_back = dataBuffer[1];

                Byte[] unit = dataBuffer.Skip(4).ToArray();

                if (dataBuffer[2] == 0XC3 && dataBuffer[3] == 0XFF)
                {


                    return CommandInfo.parseWithC3HexData(unit);
                }
                else if ((dataBuffer[2] == 0XC2 || dataBuffer[2] == 0XC1) && dataBuffer[3] == 0X00)//应答
                {
                    if(command_infos == null)
                        command_infos = new ArrayList();
                    //ArrayList list = new ArrayList();
                    return CommandInfo.parseWithHexData(unit, command_infos);

                }


                else
                {
                    return "应答标志错误";
                }
            }

            return "命令单元数据长度错误";

        }

        public Byte[] getProtocolHex()
        {
            //StringBuilder ret = new StringBuilder();

            //ret.Append(version);
            //ret.Append(keep_back);
            //ret.Append((byte)command_action);
            //ret.Append(reply_flag);

            MemoryStream s = new MemoryStream();
            s.WriteByte(version);
            s.WriteByte(keep_back);
            s.WriteByte((byte)command_action);
            s.WriteByte(reply_flag);
            for (int index = 0; index < this.command_infos.Count; index++)
            {
                CommandInfo info
                    = (CommandInfo)this.command_infos[index];
                Byte[] ret2 = info.getProtocolHex();
                s.Write(ret2, 0, ret2.Length);
            }
            // return ret.ToString();

            Byte[] ret = new Byte[s.Length];
            s.Position = 0;
            s.Read(ret, 0, (int)s.Length);
            return ret;
        }
    }




    //++++ 字符转义：由于使用16进制方式传输数据，为防止数据中出现与通信包起始标志、结束标志相同的数据而影响这两个标志的判断。在发送和接收时必须进行数据的转义，使用的转义字符是ASCII字符‘＾’（0X5E）

    //++++4．鉴权
    //无论是上位机还是听力计（DSP），收到数据包后一定要进行鉴权处理。鉴权处理分下面几个环节：起始标志/结束标志校验、CRC校验、命令编号校验、命令数据校验。如果上述任何一个环节校验未通过则认为鉴权失败，接收方应根据实际情况向发送方应答错误标志。

    //++++5．保护定时器
    //采用保护定时器的目的是在时序上保证消息或命令的可靠到达。本协议规定：在收到应答之前，主发送方必须设置保护定时器。定时器超时之前收到的应答为有效应答，否则为无效应答或发送失败或设备通信故障或在初始化时认为设备不存在。

    //上位机与听力计（DSP）间以数据包的形式进行交互，一个完整的命令包由起始标志单元、命令单元、CRC校验单元、结束标志单元4部分组成。
    class TLJCommand
    {

        byte start_flag;
        CommandUnit command_unit;
        UInt16 crc16_result;
        byte end_flag;


        //{
        //    uint8_t start_flag;//起始标志单元,固定为16进制数0X4E
        //
        //    uint16_t crc16_result;//校验单元
        //    /*校验单元：针对协议中的“命令单元”进行校验（从“命令单元”的第一个字节计算到最后一个字节），采用CCITT推荐的16位的x16+x12+x5+1(0x1021)。生成2字节的CRC校验和（低字节在前，高字节在后）。发送方必须根据“命令单元”生成2字节的CRC检验和，接收方收到完整的数据包后，根据“命令单元”生成新的CRC校验和，如果新的CRC校验和与收到的校验和相等则表明该数据包有效，否则向发送方回送“校验错”的应答。*/
        //    uint8_t end_flag;//结束标志单元,固定为16进制数0X4E
        //};

        static UInt16[] crc16tab = {
    0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
    0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
    0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
    0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
    0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
    0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
    0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
    0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
    0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
    0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
    0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
    0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
    0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
    0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
    0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
    0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
    0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
    0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
    0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
    0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
    0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
    0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
    0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
    0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
    0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
    0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
    0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
    0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
    0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
    0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
    0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
    0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
    };

        public UInt16 crc16(byte[] buf, int len)
        {

            int counter;
            UInt16 crc = 0;
            for (counter = 0; counter < len; counter++)
            {
                crc =(UInt16)((crc << 8) ^ crc16tab[((crc >> 8) ^ buf[counter]) & 0x00FF]);
            }
                
            return crc;
        }

        //-(instancetype) initWithCommandType:(enum CommandType)type action:(enum CommandAction)action info:(NSData*) info;
        //-(instancetype) initWithReplyCommand:(enum CommandAction)action info:(NSData*) info;
        //-(void) appendWithCommandType:(enum CommandType)type info:(NSData*) info;
        //-(void) appendWithCommandInfo:(CommandInfo*) info;
        //-(NSError*) parseWithHexData:(NSData*) data;
        //-(NSData*) getProtocolHex;


        //infos 命令字符串list
        public TLJCommand() {
        }
        public TLJCommand(CommandType type, CommandAction action, ArrayList infos)
        {
            this.command_unit = new CommandUnit(type, action, infos);
            this.start_flag = 0X4E;
            this.end_flag = 0X4E;
        }

        public TLJCommand(CommandAction
            action)
        {
            this.command_unit = new CommandUnit(action);
            this.start_flag = 0X4E;
            this.end_flag = 0X4E;
        }

        public void appendWithCommandInfo(CommandInfo infos)
        {
            this.command_unit.appendWithCommandInfo(infos);
        }

        public void appendWithCommandType(CommandType type, Byte[] info)
        {
            this.command_unit.appendWithCommandType(type, info);
        }

        public void appendWithCommandType(CommandType type, string info)
        {
            this.command_unit.appendWithCommandType(type, info);
        }


        public Byte[] getProtocolHex()
        {
            Stream scenter = new MemoryStream();

            Byte[] unit = command_unit.getProtocolHex();
            UInt16 crc = this.crc16(unit, unit.Length);

            scenter.Write(unit, 0, unit.Length);
            scenter.Write(BitConverter.GetBytes(crc), 0, 2);

            Byte[] center = new Byte[scenter.Length];
            scenter.Position = 0;
            scenter.Read(center, 0, (int)scenter.Length);

            Byte[] ret_center =  ClaritySend(center);

            Stream sret = new MemoryStream();
            sret.WriteByte(start_flag);
            sret.Write(ret_center, 0, ret_center.Length);
            sret.WriteByte(end_flag);


            Byte[] retByteArr = new byte[sret.Length];
            sret.Position = 0;
            sret.Read(retByteArr, 0, (int)sret.Length);
            return retByteArr;
        }


        ////*********** ClaritySend()******************
        //            5E -> 5E 5D
        //            4E -> 5E 4D
        ////*******************************************
        public static Byte[] ClaritySend(Byte[] buf)
        {
            Byte[] ret = new Byte[2 * buf.Length];
            int j = 0;
            for (int i = 0; i < buf.Length; i++)
            {
                ret[j] = (buf[i]); j++;
                if (buf[i] == 0X5E)
                {                 
                    Byte add = 0X5D;
                    ret[j] = (add);j++;
                }

            }


            Byte[] ret2 = new Byte[2 * j];
            int ii = 0;
            for (int i = 0; i < j; i++)
            {
                if ((Byte)(ret[i]) == 0X4E)
                {

                    Byte add = 0X5E;
                    Byte add2 = 0X4D;
                    ret2[ii]=(add);
                    ret2[ii+1] = (add2);

                    ii += 2;
                }
                else
                {
                    ret2[ii] = (ret[i]);
                    ii++;
                }
                
            

            }
    
            return ret2.Take(ii).ToArray();
        }

//*********** ClarityRece()******************
//		5E 4D -> 4E
//      5E 5D -> 5E
//
//*******************************************
        public static Byte[] clarityRece(Byte[] buf)
        {
            Byte[] ret = new Byte[buf.Length] ;
            int j = 0;
            for ( int i=0; i< buf.Length-1; i++)
            {
                if (buf[i] == 0X5E && buf[i + 1] == 0X4D)
                {
                    Byte add = 0X4D;
                    ret[j] = (add);
                    i++;j++;
                }
                else
                {
                    ret[j] = (buf[i]);
                    j++;
                }
        
            }
            ret[j] = (buf[buf.Length -1 ]);
            j++;


            Byte[] ret2 = new Byte[j];

            int ii = 0;
            for (int i=0; i< j - 1; i++)
            {
                if(ret[i] == 0X5E && ret[i + 1] ==0X5D)
                {
                    Byte add = 0X5E;
                    ret2[ii] = (add);
                    i++;ii++;
                }
                 else
                {
                    ret2[ii] = (ret[i]);
                    ii++;
                }
                    
        
            }
            ret2[ii] = (ret[j-1]);
            ii++;
            return ret2.Take(ii).ToArray();
        }

        public string parseWithHexData(Byte[] dataBuffer)
        {
            if (dataBuffer.Length > 2)
            {
                if (dataBuffer[0] != 0X4E || dataBuffer[dataBuffer.Length - 1] != 0X4E)
                {
                    return "开始结束字段校验错误";
                }

                //NSData* temp = [NSData dataWithBytes: dataBuffer + 1 length: data.length - 2];

                Byte[] temp = dataBuffer.Skip(1).Take(dataBuffer.Length - 2).ToArray();

                Byte[] unit = TLJCommand.clarityRece(temp);
              

                ushort crc1 =(ushort)((unit[unit.Length - 2] & 0xff) | ((unit[unit.Length - 1] & 0xff) << 8));
                ushort crc2 = crc16(unit, unit.Length - 2);

                if (crc2 != crc1)//crc16校验
                {

                    return "Crc 校验错误";
                }

                else
                {
                    Byte[] c_uint = unit.Take(unit.Length - 2).ToArray();//delete crc
                    if (command_unit == null)
                    {
                        command_unit = new CommandUnit();
                    }

                    return command_unit.parseWithHexData(c_uint);


                }
            }
            return "命令包长度错误";
        }
    }
}
